package com.sanweibook.jhook.common.util;

import com.google.common.net.MediaType;
import com.sanweibook.jhook.common.exception.JhookException;
import freemarker.template.Configuration;
import freemarker.template.Template;
import freemarker.template.TemplateException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.Base64Utils;
import org.springframework.util.FileCopyUtils;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.net.URL;
import java.util.Map;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

/**
 * Created by twg on 2017/5/27.
 */
public final class FileHandlerUtils {
    private static final Logger log = LoggerFactory.getLogger( FileHandlerUtils.class );

    private FileHandlerUtils() {
    }


    /**
     * 通过URL下载文件
     *
     * @param urlPath
     * @param fileName
     * @param response
     */
    public static void downloadWordFile(final String urlPath, final String fileName, final HttpServletResponse response) {
        try {
            response.setHeader( "Content-Disposition", "attachment; filename=" + new String( fileName.getBytes( "utf-8" ), "iso8859-1" ) );
            response.setContentType( MediaType.OCTET_STREAM.type() );
            ServletOutputStream out = response.getOutputStream();
            URL url = new URL( urlPath );
            InputStream in = url.openStream();
            FileCopyUtils.copy( in, out );
        } catch (IOException e) {
            log.error( "response is error.", e );
            throw new JhookException( e.getMessage() );
        }
    }


    /**
     * 生成文件保存的路径，默认保存在jvm的临时文件夹下
     *
     * @param folderName 自定义文件夹名
     * @return
     */
    public static String generateFilePath(final String folderName) {
        final long time = System.currentTimeMillis();
        StringBuilder sb = new StringBuilder( System.getProperty( "java.io.tmpdir" ) );
        sb.append( File.separator ).append( folderName ).append( File.separator )
                .append( time ).append( File.separator );
        return sb.toString();
    }

    /**
     * 根据默认的word模版生成，word文件
     *
     * @param paramMap 保存文件内容
     * @param filePath 保存文件路径
     * @param fileName 保存的文件名
     */
    public static void generateFile(final Map<String, String> paramMap, final String filePath, final String fileName) {
         /*生产模版文件，存放在临时文件下*/
        File file = new File( filePath );
        if (!file.exists()) {
            file.mkdirs();
        }
        File input = new File( filePath + File.separator + fileName );
        FileOutputStream outputStream = null;
        PrintWriter printWriter = null;
        try {
            outputStream = new FileOutputStream( input );
            printWriter = new PrintWriter( outputStream );

            Configuration configuration = new Configuration( Configuration.DEFAULT_INCOMPATIBLE_IMPROVEMENTS );
            configuration.setClassLoaderForTemplateLoading( Thread.currentThread().getClass().getClassLoader(), "/word/" );
            Template template = configuration.getTemplate( "word.ftl" );
            template.process( paramMap, printWriter );
            printWriter.flush();
            printWriter.close();
        } catch (IOException | TemplateException e) {
            log.error( "template process error.", e );
            throw new JhookException( e.getMessage() );
        } finally {
            if (outputStream != null) {
                try {
                    outputStream.close();
                } catch (IOException e) {
                    log.error( "outputStream close error.", e );
                }
            }
            if (printWriter != null) {
                printWriter.close();
            }
        }
    }

    /**
     * 下载zip文件
     *
     * @param filePath 需要压缩的文件路径
     * @param fileName 下载后的压缩文件名
     * @param response 输出流
     */
    public static void downloadZipFile(final String filePath, final String fileName, final HttpServletResponse response) {
        try {
            response.setHeader( "Content-Disposition", "attachment; filename=" + new String( fileName.getBytes( "utf-8" ), "iso8859-1" ) );
            downloadZipFile( filePath, response.getOutputStream() );
        } catch (IOException e) {
            log.error( "response outPutStream is error.", e );
            throw new JhookException( e.getMessage() );
        } finally {
            File file = new File( filePath );
            File[] files = file.listFiles();
            for (File _file : files) {
                if (!_file.delete()) {
                    log.info( "file name {} not delete.", _file.getName() );
                }
            }
            if (!file.delete()) {
                log.info( "file name {} not delete.", file.getName() );
            }
        }
    }


    /**
     * 下载zip文件
     *
     * @param filePath     需要压缩的文件路径
     * @param outputStream 输出流
     */
    public static void downloadZipFile(final String filePath, final OutputStream outputStream) {
        ZipOutputStream out = new ZipOutputStream( outputStream );
        File file = new File( filePath );
        File[] files = file.listFiles();
        for (File _file : files) {
            FileInputStream inputStream = null;
            byte[] bytes = new byte[0];
            try {
                inputStream = new FileInputStream( _file );
                bytes = new byte[inputStream.available()];
                out.putNextEntry( new ZipEntry( _file.getName() ) );
                int len;
                while ((len = inputStream.read( bytes )) > 0) {
                    out.write( bytes, 0, len );
                }
                out.finish();
                out.closeEntry();
                inputStream.close();
            } catch (FileNotFoundException e) {
                log.error( "the file name {} is not found.", file.getName(), e );
                throw new JhookException( e.getMessage() );
            } catch (IOException e) {
                log.error( "downloadZipFile error.", e );
                throw new JhookException( e.getMessage() );
            } finally {
                if (inputStream != null) {
                    try {
                        inputStream.close();
                    } catch (IOException e) {
                        log.error( "inputStream close error.", e );
                    }
                }

            }
        }
        try {
            out.close();
            outputStream.close();
        } catch (IOException e) {
            log.error( "close outputStream error.", e );
        }
    }


    /**
     * 通过Base64转换文件内容
     *
     * @param urlPath 文件的URL地址
     * @return
     */
    public static String convertFileToBase64(final String urlPath) {
        try {
            URL url = new URL( urlPath );
            InputStream in = url.openStream();
            byte[] bytes = FileCopyUtils.copyToByteArray( in );
            return new String( Base64Utils.encode( bytes ) );
        } catch (IOException e) {
            log.error( "file copy to bayte error.", e );
        }
        return "";
    }

    /**
     * 通过文件URL地址，生成文件保存在临时文件夹下
     *
     * @param filePath 文件保存的路径
     * @param fileUrl  文件URL地址
     * @param fileName 生成的文件名
     */
    public static void generateFile(final String filePath, final String fileUrl, final String fileName) {
         /*生产文件，存放在临时文件下*/
        File file = new File( filePath );
        if (!file.exists()) {
            file.mkdirs();
        }
        File _file = new File( filePath + File.separator + fileName );
        FileOutputStream fileOutputStream = null;
        byte[] bytes = new byte[0];
        try {
            fileOutputStream = new FileOutputStream( _file );
            bytes = getByteFromFileUrl( fileUrl );
            fileOutputStream.write( bytes );
            fileOutputStream.flush();
            fileOutputStream.close();
        } catch (FileNotFoundException e) {
            log.error( "the file name {} is not found.", fileName, e );
            throw new JhookException( e.getMessage() );
        } catch (IOException e) {
            log.error( "fileOutputStream write error.", e );
            throw new JhookException( e.getMessage() );
        } finally {
            if (fileOutputStream != null) {
                try {
                    fileOutputStream.flush();
                    fileOutputStream.close();
                } catch (IOException e) {
                    log.error( "fileOutputStream close error.", e );
                }
            }
        }
    }

    /**
     * 通过文件URL路径，获取字节
     *
     * @param fileUrl
     * @return
     */
    public static byte[] getByteFromFileUrl(final String fileUrl) throws IOException {
        URL url = new URL( fileUrl );
        InputStream in = url.openStream();
        return FileCopyUtils.copyToByteArray( in );
    }


}
